import { useEffect, type FunctionComponent } from "react";
import Scrollbars from 'react-custom-scrollbars';
import {
  InstantSearch,
  SearchBox,
  type HitsProps,
  useHits,
} from 'react-instantsearch';
import useSearchClient from "@/hooks/useSearchClient";
import type { ItemResult } from "@/types/search";
import type { SearchBoxClassNames } from "react-instantsearch/dist/es/ui/SearchBox";
import debounce from "lodash/debounce";
import useFixedHeader from "@/hooks/useFixedHeader";
import PagefindLogo from "@/assets/icon/pagefind-dark.svg";

interface PcSearchLayoutProps {
  handleClose?: () => void
}

let fixed: ReturnType<typeof useFixedHeader>

const ArticleIcon = () => (
  <svg viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" width="24" height="24"><path d="M765.78 172.14H255.04c-45.71 0-82.9 37.19-82.9 82.9v510.75c0 47.46 38.61 86.07 86.07 86.07h507.57c47.46 0 86.07-38.61 86.07-86.07V258.21c0.01-47.46-38.6-86.07-86.07-86.07zM574.71 597.03h-212.7c-15.26 0-27.63-12.37-27.63-27.63s12.37-27.63 27.63-27.63H574.7c15.26 0 27.63 12.37 27.63 27.63 0.01 15.26-12.36 27.63-27.62 27.63z m88.59-163.55H362.01c-15.26 0-27.63-12.37-27.63-27.63s12.37-27.63 27.63-27.63H663.3c15.26 0 27.63 12.37 27.63 27.63s-12.37 27.63-27.63 27.63z" fill="#ffffff"></path></svg>
)

function Hit({ hit }: { hit: ItemResult }) {
  const handleClick = () => {
    const [link, id] = hit.link.split('#')
    if (window.location.href.split('#')[0].includes(link)) {
      requestAnimationFrame(() => {
        fixed(id)
      })
    }
    else window.location.href = hit.link
  }

  return <div onClick={handleClick} className="p-5 w-full flex items-center justify-between h-20 cursor-pointer !rounded-[10px] border-[1px] border-transparent border-b-white/20 hover:border-white">
    <div className="flex items-center w-full">
      <ArticleIcon />
      <div className="flex flex-col ml-4 w-[calc(100%-2.8rem)]">
        {/* title contains <mark></mark> to highlight keyword */}
        <p className="font-bold text-lg" dangerouslySetInnerHTML={{ __html: hit.title }}></p>
        {hit.subTitle && <p className="text-sm whitespace-nowrap overflow-hidden text-ellipsis w-full" dangerouslySetInnerHTML={{ __html: hit.subTitle }}></p>}
      </div>
    </div>
  </div>
}

const ItemResultTypeList: Extract<ItemResult, { type: string }>["type"][] = [
  "物品",
  "方块",
  "Liver",
  "Buff/Debuff",
  "附魔",
  "生物群系",
  "实体",
  "FAQ",
  "已收藏",
  "最近搜索",
  "梗",
  "其他"
]

function MyHits({ onClick: handleClose, ...props }: HitsProps<ItemResult> & React.HTMLProps<Scrollbars>) {
  const { hits } = useHits(props);

  const map: { type: string, children: ItemResult[] }[] = ItemResultTypeList.map((v) => ({
    type: v,
    children: []
  }))

  // todo!: optimize speed
  const otherQueue: ItemResult[] = []
  hits.forEach((v) => {
    let flag = false
    map.forEach((item) => {
      if (v.type === item.type && ItemResultTypeList.includes(v.type)) {
        item.children.push(v)
        flag = true
      }
    })
    if (!flag) {
      otherQueue.push(v)
    }
  })
  map.some((v) => v.type === "其他" && v.children.push(...otherQueue))

  return <Scrollbars
    style={{
      height: 380
    }}
    renderThumbVertical={(_, props) => <div {...props} className="bg-white/50 rounded-[5px]" />}
    {...props}
  >
    <div onClick={handleClose}>
      {map.map(({ type, children }) => (
        children.length ? <div className="pr-4" key={type}>
          <p className="mb-6 mt-4 text-sm flex justify-between">{type}</p>
          {children.map((v, i) => <Hit key={i} hit={v} />)}
        </div> : null
      ))}
    </div>
  </Scrollbars>
}

const SearchClassNames: Partial<SearchBoxClassNames> = {
  "input": "bg-transparent border-white/50 border-[1px] rounded-[5px] focus:border-white text-white !py-2 w-full pl-9 pr-4 outline-none",
  form: "bg-transparent relative",
  submit: "absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4",
  submitIcon: "fill-white w-4 h-4",
  reset: "absolute right-4 top-1/2 -translate-y-1/2 w-4 h-4",
  resetIcon: "fill-white w-3 h-3",
  loadingIndicator: "absolute right-4 top-1/2 -translate-y-1/2 w-4 h-4",
  loadingIcon: "fill-white w-4 h-4",
}

const queryFunc: Parameters<typeof SearchBox>["0"]["queryHook"] = debounce((q, h) => {
  h(q)
}, 500)

const PcSearchLayout: FunctionComponent<PcSearchLayoutProps> = ({ handleClose }) => {
  const searchClient = useSearchClient();
  useEffect(() => {
    fixed = useFixedHeader()
  }, [])

  return (
    <div className="relative max-w-[720px] w-[90%] mx-auto mt-12 p-4 black_module" id="search-box">
      <InstantSearch searchClient={searchClient} indexName="wiki">
        <SearchBox
          queryHook={queryFunc}
          autoFocus
          className="rounded-[5px] shadow-[0_2px_4px_rgba(0,0,0,0.5)]" classNames={SearchClassNames} placeholder="想要找什么？" />
        <div className="pt-2">
          <MyHits onClick={handleClose} />
        </div>
        <div className="flex mt-4 gap-2 items-center font-bold">
          Search powered by<img src={PagefindLogo.src} className="h-5 mt-1" alt="" />
        </div>
      </InstantSearch>
    </div>
  );
}

export default PcSearchLayout;